package test;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.mysql.jdbc.Connection;

import handler.DBConnector;

/**
 * Overrides DBConnector to not automatically commit new changes. This will
 * allow integration testing of the database without interfering with the
 * regular use of the program
 * 
 * @author Jared Schlicht
 */
public class SerializedDBConnector extends DBConnector {
    
    /**
     * Establishes a new connection to the database. All operations with this
     * connection will be performed in a serializable transaction.
     */
    @Override
    public void connect() {
        super.connect();
        try {
            this.connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Overrides the default disconnect behavior. This method does nothing
     * in order to keep the current transaction alive.
     */
    @Override
    public void disconnect() {
        // Do nothing, as we do not want to end the transaction yet
    }
    
    /**
     * Really disconnects the current connection.
     */
    public void reallyDisconnect() {
        super.disconnect();
    }
    
    /**
     * Rolls back the current transaction. This will undo any operations
     * performed by this connection since  the transaction was started.
     */
    public void rollback() {
        try {
            this.connection.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Generic Execution Handler.  Handles CRUD statements.  Values are determined by casting
     * the object type dynamically during execution. Insert will not return a ResultSet.
     * 
     * This method will NOT commit any transactions after executing a query,
     * unlike the stock DBConnector class provided in the handler package. This
     * allows integration testing, since the database state can be rolled
     * back to a clean state.
     * 
     * @param query string representing a mysql query statement.
     * @param vals an object array of parameters for the query statement.
     * @return set of results from the mysql query or null if no set was retrieved.
     */
    @Override
    protected ResultSet execute(String query, Object[] vals) {
        
        try{
            connection.setAutoCommit(false);
            PreparedStatement ps = connection.prepareStatement(query);
            
            for(int i = 0; i < vals.length; i++)
                ps.setObject(i+1, vals[i].getClass().cast(vals[i]));
            
            ps.execute();
            
            return ps.getResultSet();
            
        } catch(Exception e) {
            e.printStackTrace();
        }
        
        return null;
    }
    
}
